package com.paipaideli.common.utils;

import android.text.TextUtils;
import android.util.Log;

import com.alibaba.sdk.android.oss.ClientException;
import com.alibaba.sdk.android.oss.OSSClient;
import com.alibaba.sdk.android.oss.ServiceException;
import com.alibaba.sdk.android.oss.callback.OSSCompletedCallback;
import com.alibaba.sdk.android.oss.common.auth.OSSCredentialProvider;
import com.alibaba.sdk.android.oss.common.auth.OSSPlainTextAKSKCredentialProvider;
import com.alibaba.sdk.android.oss.model.DeleteObjectRequest;
import com.alibaba.sdk.android.oss.model.PutObjectRequest;
import com.paipaideli.BuildConfig;
import com.paipaideli.MyApplication;
import com.paipaideli.common.utils.BitmapUtil;


import java.io.File;
import java.io.IOException;
import java.util.Calendar;
import java.util.UUID;

import io.reactivex.Observable;
import io.reactivex.schedulers.Schedulers;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;


/**
 * Created by wangJia on 2017/3/27.
 */

public class OssFileUploadUtil {


    // 需要配置以下字段为有效的值
    private static final String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";


    private static final String TAG = "OssFileUploadUtil";
    private static OSSPlainTextAKSKCredentialProvider provider;
    private static OSSClient client;
    private static String PATH_ROOT = "avatar/";
    private static OkHttpClient okHttpClient;
    private static String accessKeyId="LTAI4FezQuSRJaZCSWQWnqcM";
    private static String accessKeySecret="sHZLAT9nxGdenhckvQb8HqAJlKP16g";

    public enum NameSpace {

        AVATAR, //头像

    }

    public static PutObjectRequest upload(String filePath) throws ClientException, ServiceException, IOException {
        return uploadSync(filePath, NameSpace.AVATAR);
    }

    /**
     * 同步上传文件
     *
     * @param filePath  local file path
     * @param nameSpace remote path
     * @return String uploaded file path in remote
     * @throws ClientException  client error
     * @throws ServiceException service error
     */
    public static PutObjectRequest uploadSync(String filePath, NameSpace nameSpace) throws ClientException, ServiceException, IOException {
        initOSS();
        processNameSpace(nameSpace);
        PutObjectRequest request = createRequest(filePath, filePath);
        Log.d(TAG, "upload file sync : " + filePath);
        if (checkFileExists(request.getObjectKey())) {
            return request;
        } else {
            String newFilePath = MyApplication.getInstanse().getAppCacheDir();
            Log.d(TAG, "compress image output to file path : " + newFilePath);
            File newFile = new File(newFilePath + "/." + System.currentTimeMillis() + ".jpg");
            BitmapUtil.compressAndGenImage(filePath, newFile.getAbsolutePath(), 600);
            request.setObjectKey(getObjectKey(newFile.getAbsolutePath()));
            request.setUploadFilePath(newFile.getAbsolutePath());
            uploadSync(request);

            // 前面需要通过原始上传的文件来确定是否为新增的照片。
            request.setUploadFilePath(filePath);
            newFile.deleteOnExit();
        }
        return request;
    }

    /**
     * 同步上传文件
     *
     * @param filePath  local file path
     * @param nameSpace remote path
     * @return String uploaded file path in remote
     * @throws ClientException  client error
     * @throws ServiceException service error
     */
    public static PutObjectRequest uploadSync2(String filePath, NameSpace nameSpace) throws ClientException, ServiceException, IOException {
        initOSS();
        processNameSpace(nameSpace);
        PutObjectRequest request = new PutObjectRequest(BuildConfig.bucketName, getObjectKey(filePath), filePath);
        Log.d(TAG, "upload file sync : " + filePath);
        return request;
    }

    public static void asyncPutObject(PutObjectRequest put, OSSCompletedCallback callback) {
        client.asyncPutObject(put, callback);
    }



    /*
    * @param  delpath
    *
    *
    *
    * */
    //  public static DeleteObjectRequest delete = new DeleteObjectRequest("<bucketName>", "<objectKey>");

    public static DeleteObjectRequest deleteSync(String delPath) throws ClientException, ServiceException {
        initOSS();
        DeleteObjectRequest deleteObjectRequest = new DeleteObjectRequest(BuildConfig.bucketName, delPath);
        return deleteObjectRequest;

    }

    /**
     * 得到一个上传的Observable
     *
     * @param filePath  file path
     * @param nameSpace name space
     * @return Observable
     */
    public static Observable<PutObjectRequest> uploadObservable(String filePath, NameSpace nameSpace) {
        if (TextUtils.isEmpty(filePath)) {
            return Observable.empty();
        }
        initOSS();
        return Observable.just(filePath)
                .observeOn(Schedulers.io())
                .map(s -> {
                    return uploadSync(s, nameSpace);
                });
    }

    /**
     * 异步上传文件
     *
     * @param filePath   local file path
     * @param remotePath remote path
     * @param callback   call back
     */
    @SuppressWarnings("unused")
    public void uploadAsync(String filePath, String remotePath, OSSCompletedCallback callback) {
        initOSS();
        processNameSpace(NameSpace.AVATAR);
        PutObjectRequest request = createRequest(filePath, remotePath);
        Log.d(TAG, "upload file async : " + filePath);
        uploadAsync(request, callback);
    }

    public static void deleteFile(String path) {
        initOSS();
        DeleteObjectRequest request = new DeleteObjectRequest(BuildConfig.bucketName, path);
        try {
            client.deleteObject(request);
        } catch (Exception e) {
            Log.e(TAG, "delete object", e);
        }
    }


    public static void deleteFile(String path, OSSCompletedCallback callback) {
        initOSS();
        DeleteObjectRequest request = new DeleteObjectRequest(BuildConfig.bucketName, path);
        try {
            client.asyncDeleteObject(request, callback);
        } catch (Exception e) {
            Log.e(TAG, "delete object", e);
        }
    }

    private static void processNameSpace(NameSpace nameSpace) {
        switch (nameSpace) {

            case AVATAR:
                PATH_ROOT = "avatar/";
                break;
            default:
                throw new RuntimeException("上传空间不正确");
        }
    }

    private static void uploadSync(PutObjectRequest request) throws ClientException, ServiceException {
        client.putObject(request);
    }

    private static void uploadAsync(PutObjectRequest request, OSSCompletedCallback callback) {
        client.asyncPutObject(request, callback);
    }

    private static PutObjectRequest createRequest(String filePath, String path) {
        PutObjectRequest putObjectRequest = new PutObjectRequest(BuildConfig.bucketName, filePath, path);
        return new PutObjectRequest(BuildConfig.bucketName, filePath, path);
    }

    private static boolean checkFileExists(String objectKey) {
        if (okHttpClient == null) {
            okHttpClient = new OkHttpClient();
        }
        String url = BuildConfig.photo + objectKey;
        Request request = new Request.Builder().head()
                .url(url)
                .build();
        Response response = null;
        try {
            response = okHttpClient.newCall(request).execute();
        } catch (IOException e) {
            return false;
        }
        return response != null && response.code() == 200;
    }

    private static String getObjectKey(String filePath) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(System.currentTimeMillis());
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH) + 1;
        int day = calendar.get(Calendar.DAY_OF_MONTH);
        String imgName = getImageName(filePath);

        String key = PATH_ROOT + year + "/" + month + "/" + day + "/" + imgName;
        Log.d(TAG, "file local path : " + filePath);
        Log.d(TAG, "generate a key : " + key);
        return key;
    }

    private static String getImageName(String filePath) {
        Log.d(TAG, "generate name : " + filePath);
        String[] strings = filePath.split("/");
        String temp = strings[strings.length - 1];
        String endTemp = temp.substring(temp.lastIndexOf(".") + 1, temp.length());
        return UUID.randomUUID() + "." + endTemp;
    }

    private static void initOSS() {
        if (client == null) {
            Log.d(TAG, "init oss");
            synchronized (OSSClient.class) {
                client = new OSSClient(MyApplication.getInstanse(), endpoint, getCredential());
            }
        }
    }

    private static OSSPlainTextAKSKCredentialProvider getCredential() {
        if (provider == null) {
            Log.d(TAG, "init oss credential");
            synchronized (OSSCredentialProvider.class) {
                provider = new OSSPlainTextAKSKCredentialProvider(accessKeyId, accessKeySecret);
            }
        }
        return provider;
    }
}
